package com.zxjbyte.yiyi.framework.common.enums;

import java.util.EnumSet;
import java.util.List;
import java.util.Objects;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * 通用的枚举接口
 *
 * @Author zhangxingjia
 * @Date 2023/10/7 11:44
 * @Version: 1.0
 */
public interface CommonEnum<T> {

    /**
     * 获取code值
     * @return
     */
    T getCode();

    /**
     * 单个code精确匹配单个枚举，直接返回枚举
     *
     * @param clazz 枚举实体类
     * @param code  枚举code
     * @param <T>   code的类型
     * @param <E>   枚举类型
     * @return 返回对应枚举
     */
    static <T, E extends Enum<E> & CommonEnum<?>> E getEnum(Class<E> clazz, T code) {
        return getEnum(clazz, f -> Objects.equals(f.getCode(), code));
    }

    /**
     * 指定条件匹配单个枚举，直接返回枚举
     *
     * @param clazz     实体类
     * @param predicate 判断条件
     * @param <E>       枚举类型
     * @return 返回对应枚举
     */
    static <E extends Enum<E> & CommonEnum<?>> E getEnum(Class<E> clazz, Predicate<E> predicate) {
        EnumSet<E> all = EnumSet.allOf(clazz);
        return all.stream().filter(predicate).findFirst().orElse(null);
    }

    /**
     *
     * @param clazz 实体类
     * @param predicate 判断条件
     * @param func 二次函数处理
     * @param <R> 返回类型
     * @param <E> 枚举类型
     * @return 返回对应枚举
     */
    static <R, E extends Enum<E> & CommonEnum<?>> R getEnum(Class<E> clazz, Predicate<E> predicate, Function<E, R> func) {
        EnumSet<E> all = EnumSet.allOf(clazz);
        return all.stream().filter(predicate).findFirst().map(func).orElse(null);
    }

    /**
     * 指定条件匹配枚举，返回枚举集合
     *
     * @param clazz     实体类
     * @param predicate 判断条件
     * @param <E>       枚举类型
     * @return 返回枚举集合
     */
    static <E extends Enum<E> & CommonEnum<?>> List<E> getEnums(Class<E> clazz, Predicate<E> predicate) {
        EnumSet<E> all = EnumSet.allOf(clazz);
        return all.stream().filter(predicate).collect(Collectors.toList());
    }

    /**
     * 指定条件匹配枚举，返回枚举集合
     *
     * @param clazz     实体类
     * @param predicate 判断条件
     * @param func 二次函数处理
     * @param <R>       返回类型
     * @param <E>       枚举类型
     * @return 返回枚举集合
     */
    static <R, E extends Enum<E> & CommonEnum<?>> List<R> getEnums(Class<E> clazz, Predicate<E> predicate, Function<E, R> func) {
        EnumSet<E> all = EnumSet.allOf(clazz);
        return all.stream().filter(predicate).map(func).collect(Collectors.toList());
    }

}
